/**
 @file ctc_asw_stats.c

 @date 2020-08-22

 @version v2.0

*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_asw_common.h"
#include "ctc_asw_stats.h"

#include "asw/include/drv_api.h"
/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/
#define CTC_ASW_STATS_MTU2_PKT_MIN_LENGTH 1519
#define CTC_ASW_STATS_MTU2_PKT_MAX_LENGHT 16383
/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
/****************************************************************************
 *
* Function
*
*****************************************************************************/

int32
ctc_asw_stats_set_mac_stats_cfg(uint8 lchip, uint32 gport, ctc_mac_stats_prop_type_t mac_stats_prop_type, ctc_mac_stats_property_t prop_data)
{
    JumboFrameLen_m jumbo_frame_len;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;

    CTC_MAX_GPORT_CHECK(gport);
    if (CTC_STATS_PACKET_LENGTH_MTU2 == mac_stats_prop_type)
    {
        CTC_VALUE_RANGE_CHECK(prop_data.data.length, CTC_ASW_STATS_MTU2_PKT_MIN_LENGTH, CTC_ASW_STATS_MTU2_PKT_MAX_LENGHT);
    }

    sal_memset(&jumbo_frame_len, 0, sizeof(jumbo_frame_len));

    CTC_API_LOCK(lchip);
    switch (mac_stats_prop_type)
    {
        case CTC_STATS_PACKET_LENGTH_MTU2:
            SetJumboFrameLen(V,len_f, &jumbo_frame_len, prop_data.data.length);
            cmd = DRV_IOW(JumboFrameLen_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip,gport,cmd,&jumbo_frame_len);
            break;

        default:
            ret = CTC_E_INVALID_PARAM;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_stats_get_mac_stats_cfg(uint8 lchip, uint32 gport, ctc_mac_stats_prop_type_t mac_stats_prop_type, ctc_mac_stats_property_t* p_prop_data)
{
    JumboFrameLen_m jumbo_frame_len;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;

    CTC_PTR_VALID_CHECK(p_prop_data);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    switch (mac_stats_prop_type)
    {
        case CTC_STATS_PACKET_LENGTH_MTU2:
            cmd = DRV_IOR(JumboFrameLen_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip,gport,cmd,&jumbo_frame_len);
            p_prop_data->data.length = GetJumboFrameLen(V,len_f, &jumbo_frame_len);
            break;

        default:
            ret = CTC_E_INVALID_PARAM;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_stats_get_mac_stats(uint8 lchip, uint32 gport, ctc_mac_stats_dir_t dir, ctc_mac_stats_t* p_stats)
{
    uint32 cmd = 0;
    ds_t mib_stats;
    uint32  stats_temp[2] = {0};

    CTC_PTR_VALID_CHECK(p_stats);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    switch (dir)
    {
        case CTC_STATS_MAC_STATS_RX:
            cmd = DRV_IOR(MibRx_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip,gport,cmd,&mib_stats));
            if (CTC_STATS_MODE_PLUS == p_stats->stats_mode)
            {
                GetMibRx(A, rxoctets_f, &mib_stats,stats_temp);
                p_stats->u.stats_plus.stats.rx_stats_plus.all_octets = ((uint64)stats_temp[1]<<32) | stats_temp[0];
                p_stats->u.stats_plus.stats.rx_stats_plus.all_pkts = GetMibRx(V, rxjumbopkt_f, &mib_stats) + GetMibRx(V, rxpkts1024tomaxpktoctets_f, &mib_stats) + \
                                                                     GetMibRx(V, rxpkts512to1023octets_f, &mib_stats) + GetMibRx(V, rxpkts256to511octets_f, &mib_stats) + \
                                                                     GetMibRx(V, rxpkts128to255octets_f, &mib_stats) + GetMibRx(V, rxpkts65to127octets_f, &mib_stats) + \
                                                                     GetMibRx(V, rxpkts64octets_f, &mib_stats) + GetMibRx(V, rxfragments_f, &mib_stats) + GetMibRx(V, rxundersizepkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.ucast_pkts = GetMibRx(V, rxunicastpkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.mcast_pkts = GetMibRx(V, rxmulticastpkts_f, &mib_stats) - GetMibRx(V, rxpausepkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.bcast_pkts = GetMibRx(V, rxbroadcastpkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.runts_pkts = GetMibRx(V, rxundersizepkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.giants_pkts = GetMibRx(V, rxoversizepkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.pause_pkts = GetMibRx(V, rxpausepkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.crc_pkts = GetMibRx(V, rxfcserrors_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.fragments_pkts = GetMibRx(V, rxfragments_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.jabber_pkts = GetMibRx(V, rxjabbers_f, &mib_stats);
                p_stats->u.stats_plus.stats.rx_stats_plus.jumbo_events = GetMibRx(V, rxjumbopkt_f, &mib_stats);
            }
            else
            {
                p_stats->u.stats_detail.stats.rx_stats.good_jumbo_pkts = GetMibRx(V, rxgoodjumbos_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.bad_jumbo_pkts = GetMibRx(V, rxjumbopkt_f, &mib_stats)-GetMibRx(V, rxgoodjumbos_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.pkts_1024_to_1518 = GetMibRx(V, rxpkts1024tomaxpktoctets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.pkts_512_to_1023 = GetMibRx(V, rxpkts512to1023octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.pkts_256_to_511 = GetMibRx(V, rxpkts256to511octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.pkts_128_to_255 = GetMibRx(V, rxpkts128to255octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.pkts_65_to_127 = GetMibRx(V, rxpkts65to127octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.pkts_64 = GetMibRx(V, rxpkts64octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_63_pkts = GetMibRx(V, rxpkts60to63octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_ucast_pkts = GetMibRx(V, rxunicastpkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_mcast_pkts = GetMibRx(V, rxmulticastpkts_f, &mib_stats)-GetMibRx(V, rxpausepkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_bcast_pkts = GetMibRx(V, rxbroadcastpkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.fcs_error_pkts = GetMibRx(V, rxfcserrors_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_pause_pkts = GetMibRx(V, rxpausepkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_oversize_pkts = GetMibRx(V, rxjumbopkt_f, &mib_stats) + GetMibRx(V, rxjabbers_f, &mib_stats);
                p_stats->u.stats_detail.stats.rx_stats.good_undersize_pkts = GetMibRx(V, rxundersizepkts_f, &mib_stats);
            }
            break;

        case CTC_STATS_MAC_STATS_TX:
            cmd = DRV_IOR(MibTx_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip,gport,cmd,&mib_stats));
            if (CTC_STATS_MODE_PLUS == p_stats->stats_mode)
            {
                GetMibTx(A, txoctets_f, &mib_stats,stats_temp);
                p_stats->u.stats_plus.stats.rx_stats_plus.all_octets = ((uint64)stats_temp[1]<<32) | stats_temp[0];
                p_stats->u.stats_plus.stats.tx_stats_plus.all_pkts = GetMibTx(V, txmorethanjumbopkt_f, &mib_stats) + GetMibTx(V, txjumbopkt_f, &mib_stats) + \
                                                                     GetMibTx(V, txpkts1024tomaxpktoctets_f, &mib_stats) + \
                                                                     GetMibTx(V, txpkts512to1023octets_f, &mib_stats) + GetMibTx(V, txpkts256to511octets_f, &mib_stats) + \
                                                                     GetMibTx(V, txpkts128to255octets_f, &mib_stats) + GetMibTx(V, txpkts65to127octets_f, &mib_stats) + \
                                                                     GetMibTx(V, txpkts64octets_f, &mib_stats)+ GetMibTx(V, txpkts60to63octets_f, &mib_stats);
                p_stats->u.stats_plus.stats.tx_stats_plus.ucast_pkts = GetMibTx(V, txunicastpkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.tx_stats_plus.mcast_pkts = GetMibTx(V, txmulticastpkts_f, &mib_stats)-GetMibTx(V, txpausepkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.tx_stats_plus.bcast_pkts = GetMibTx(V, txbroadcastpkts_f, &mib_stats);
                p_stats->u.stats_plus.stats.tx_stats_plus.jumbo_events = GetMibTx(V, txjumbopkt_f, &mib_stats);
            }
            else
            {
                p_stats->u.stats_detail.stats.tx_stats.jumbo_pkts = GetMibTx(V, txjumbopkt_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_1024_to_1518 = GetMibTx(V, txpkts1024tomaxpktoctets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_512_to_1023 = GetMibTx(V, txpkts512to1023octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_256_to_511 = GetMibTx(V, txpkts256to511octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_128_to_255 = GetMibTx(V, txpkts128to255octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_65_to_127 = GetMibTx(V, txpkts65to127octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_64 = GetMibTx(V, txpkts64octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.pkts_63 = GetMibTx(V, txpkts60to63octets_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.good_pause_pkts = GetMibTx(V, txpausepkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.good_ucast_pkts = GetMibTx(V, txunicastpkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.good_mcast_pkts = GetMibTx(V, txmulticastpkts_f, &mib_stats)-GetMibTx(V, txpausepkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.good_bcast_pkts = GetMibTx(V, txbroadcastpkts_f, &mib_stats);
                p_stats->u.stats_detail.stats.tx_stats.oversize_pkts = GetMibTx(V, txmorethanjumbopkt_f, &mib_stats) + GetMibTx(V, txjumbopkt_f, &mib_stats);
            }
            break;

        default:
            CTC_API_UNLOCK(lchip);
            return CTC_E_INVALID_PARAM;
    }
    CTC_API_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
ctc_asw_stats_clear_mac_stats(uint8 lchip, uint32 gport, ctc_mac_stats_dir_t dir)
{
    uint32 cmd = 0;
    MibCfg_m mib_cfg;
    int32 ret = CTC_E_NONE;

    CTC_MAX_GPORT_CHECK(gport);
    CTC_MAX_VALUE_CHECK(dir, CTC_STATS_MAC_STATS_TX);

    sal_memset(&mib_cfg, 0, sizeof(MibCfg_m));

    CTC_API_LOCK(lchip);
    cmd = DRV_IOW(MibCfg_t, DRV_ENTRY_FLAG);

    SetMibCfg(V,mibCmdChn_f, &mib_cfg, gport);
    SetMibCfg(V,mibCmdDir_f, &mib_cfg, (CTC_STATS_MAC_STATS_TX == dir)?1:0);
    SetMibCfg(V,mibCmd_f, &mib_cfg, 1);
    SetMibCfg(V,mibCmdEn_f, &mib_cfg, 1);
    ret = DRV_IOCTL(lchip,0,cmd,&mib_cfg);

    SetMibCfg(V,mibCmdEn_f, &mib_cfg, 0);
    ret = ret ? ret:DRV_IOCTL(lchip,0,cmd,&mib_cfg);

    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_stats_set_drop_packet_stats_en(uint8 lchip, ctc_stats_discard_t bitmap, bool enable)
{
    uint32 cmd = 0;
    IngressCounterCtrl_m ing_cnt_ctrl;
    uint16 idx = 0;

    sal_memset(&ing_cnt_ctrl, 0, sizeof(ing_cnt_ctrl));
    if (!CTC_FLAG_ISSET(bitmap, CTC_STATS_FLOW_DISCARD_STATS))
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_API_LOCK(lchip);
    SetIngressCounterCtrl(V,ctrl_f, &ing_cnt_ctrl, enable?0:1);
    cmd = DRV_IOW(IngressCounterCtrl_t, DRV_ENTRY_FLAG);
    for(idx=0; idx<=CTC_ASW_MAX_STATS_ID; idx++)
    {
        CTC_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip,idx,cmd,&ing_cnt_ctrl));
    }
    CTC_API_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
ctc_asw_stats_get_drop_packet_stats_en(uint8 lchip, ctc_stats_discard_t bitmap, bool* enable)
{
    uint32 cmd = 0;
    IngressCounterCtrl_m ing_cnt_ctrl;
    int32 ret = CTC_E_NONE;

    CTC_API_LOCK(lchip);
    if (CTC_FLAG_ISSET(bitmap, CTC_STATS_FLOW_DISCARD_STATS))
    {
        cmd = DRV_IOR(IngressCounterCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip,0,cmd,&ing_cnt_ctrl);
        *enable = (GetIngressCounterCtrl(V,ctrl_f, &ing_cnt_ctrl)==1)?0:1;
    }
    else
    {
        ret = CTC_E_INVALID_PARAM;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_stats_get_stats(uint8 lchip, uint32 stats_id, ctc_stats_basic_t* p_stats)
{
    uint32 cmd = 0;
    IngressCounterTable_m ing_cnt_tab;
    uint32 count[2] = {0};
    uint64 tmp = 0;
    int32 ret = 0;

    CTC_PTR_VALID_CHECK(p_stats);
    CTC_MAX_VALUE_CHECK(stats_id, CTC_ASW_MAX_STATS_ID);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressCounterTable_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip,stats_id,cmd,&ing_cnt_tab);

    GetIngressCounterTable(A, byteCnt_f, &ing_cnt_tab, &count);
    tmp |= count[1];
    tmp <<= 32;
    tmp |= count[0];
    p_stats->byte_count = tmp;
    p_stats->packet_count = GetIngressCounterTable(V, frameCnt_f, &ing_cnt_tab);

    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_stats_clear_stats(uint8 lchip, uint32 stats_id)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t ds;

    CTC_MAX_VALUE_CHECK(stats_id, CTC_ASW_MAX_STATS_ID);

    sal_memset(ds, 0, sizeof(ds_t));

    CTC_API_LOCK(lchip);
    SetCounterCtrl(V,cntRcEn_f, &ds, 1);
    cmd = DRV_IOW(CounterCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip,0,cmd,&ds);

    cmd = DRV_IOR(IngressCounterTable_t, DRV_ENTRY_FLAG);
    ret = ret?ret:DRV_IOCTL(lchip,stats_id,cmd,&ds);

    SetCounterCtrl(V,cntRcEn_f, &ds, 0);
    cmd = DRV_IOW(CounterCtrl_t, DRV_ENTRY_FLAG);
    ret = ret?ret:DRV_IOCTL(lchip,0,cmd,&ds);
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_stats_init(uint8 lchip, void* stats_global_cfg)
{
    return CTC_E_NONE;
}

int32
ctc_asw_stats_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}
